/**
 * StorageManager - 本地存储管理器
 * 处理游戏数据的序列化、反序列化和本地存储操作
 */

import type { GameSettings, ScoreRecord, GameStats } from '../stores/gameStore'
import type { Character } from './Character'

/**
 * 游戏数据接口
 */
export interface GameData {
  settings: GameSettings
  characterManager: any
  gameStats: GameStats
  scoreRecords: ScoreRecord[]
  achievements: Achievement[]
  leaderboard: LeaderboardEntry[]
  version: string
  lastSaved: Date
}

/**
 * 成就数据接口
 */
export interface Achievement {
  id: string
  name: string
  description: string
  icon: string
  category: AchievementCategory
  condition: AchievementCondition
  reward: AchievementReward
  isUnlocked: boolean
  unlockedAt?: Date
  progress: number
  maxProgress: number
}

/**
 * 成就类别枚举
 */
export enum AchievementCategory {
  SCORE = 'score',
  DISTANCE = 'distance',
  COLLECTION = 'collection',
  SURVIVAL = 'survival',
  SPECIAL = 'special',
  CHARACTER = 'character'
}

/**
 * 成就条件接口
 */
export interface AchievementCondition {
  type: 'score' | 'distance' | 'coins' | 'games' | 'powerups' | 'characters' | 'survival'
  value: number
  operator: 'gte' | 'lte' | 'eq' | 'gt' | 'lt'
}

/**
 * 成就奖励接口
 */
export interface AchievementReward {
  type: 'coins' | 'character' | 'title' | 'badge'
  value: number | string
  description: string
}

/**
 * 排行榜条目接口
 */
export interface LeaderboardEntry {
  id: string
  playerName: string
  score: number
  distance: number
  character: string
  date: Date
  achievements: number
}

/**
 * 存储错误类型
 */
export enum StorageErrorType {
  QUOTA_EXCEEDED = 'quota_exceeded',
  ACCESS_DENIED = 'access_denied',
  CORRUPTION = 'corruption',
  VERSION_MISMATCH = 'version_mismatch',
  SERIALIZATION_ERROR = 'serialization_error'
}

/**
 * 存储错误类
 */
export class StorageError extends Error {
  constructor(
    public type: StorageErrorType,
    message: string,
    public originalError?: Error
  ) {
    super(message)
    this.name = 'StorageError'
  }
}

/**
 * 存储配置接口
 */
export interface StorageConfig {
  storageKey: string
  version: string
  maxBackups: number
  compressionEnabled: boolean
  encryptionEnabled: boolean
  autoSave: boolean
  saveInterval: number
}

/**
 * 默认存储配置
 */
const DEFAULT_STORAGE_CONFIG: StorageConfig = {
  storageKey: 'vue-parkour-game',
  version: '1.0.0',
  maxBackups: 3,
  compressionEnabled: false,
  encryptionEnabled: false,
  autoSave: true,
  saveInterval: 30000 // 30秒
}

/**
 * 本地存储管理器类
 */
export class StorageManager {
  private config: StorageConfig
  private autoSaveTimer?: number
  private isInitialized = false

  constructor(config: Partial<StorageConfig> = {}) {
    this.config = { ...DEFAULT_STORAGE_CONFIG, ...config }
  }

  /**
   * 初始化存储管理器
   */
  async initialize(): Promise<void> {
    try {
      // 检查localStorage可用性
      this.checkStorageAvailability()
      
      // 清理过期的备份数据（在测试环境中可能会失败，所以用try-catch包装）
      try {
        await this.cleanupOldBackups()
      } catch (cleanupError) {
        console.warn('清理备份时出错，但不影响初始化:', cleanupError)
      }
      
      // 启动自动保存
      if (this.config.autoSave) {
        this.startAutoSave()
      }
      
      this.isInitialized = true
    } catch (error) {
      throw new StorageError(
        StorageErrorType.ACCESS_DENIED,
        '存储管理器初始化失败',
        error as Error
      )
    }
  }

  /**
   * 检查localStorage可用性
   */
  private checkStorageAvailability(): void {
    try {
      const testKey = '__storage_test__'
      localStorage.setItem(testKey, 'test')
      localStorage.removeItem(testKey)
    } catch (error) {
      throw new StorageError(
        StorageErrorType.ACCESS_DENIED,
        'localStorage不可用'
      )
    }
  }

  /**
   * 保存游戏数据
   */
  async saveGameData(data: Partial<GameData>): Promise<void> {
    if (!this.isInitialized) {
      await this.initialize()
    }

    try {
      // 获取现有数据
      const existingData = await this.loadGameData()
      
      // 合并数据
      const gameData: GameData = {
        ...existingData,
        ...data,
        version: this.config.version,
        lastSaved: new Date()
      }

      // 序列化数据
      const serializedData = this.serializeData(gameData)
      
      // 创建备份
      await this.createBackup()
      
      // 保存到localStorage
      localStorage.setItem(this.config.storageKey, serializedData)
      
    } catch (error) {
      if (error instanceof DOMException && error.code === 22) {
        throw new StorageError(
          StorageErrorType.QUOTA_EXCEEDED,
          '存储空间不足',
          error
        )
      }
      throw new StorageError(
        StorageErrorType.SERIALIZATION_ERROR,
        '数据保存失败',
        error as Error
      )
    }
  }

  /**
   * 加载游戏数据
   */
  async loadGameData(): Promise<GameData> {
    if (!this.isInitialized) {
      await this.initialize()
    }

    try {
      const savedData = localStorage.getItem(this.config.storageKey)
      
      if (!savedData) {
        return this.getDefaultGameData()
      }

      const gameData = this.deserializeData(savedData)
      
      // 版本检查
      if (gameData.version !== this.config.version) {
        console.warn(`数据版本不匹配: ${gameData.version} vs ${this.config.version}`)
        // 这里可以添加数据迁移逻辑
        gameData.version = this.config.version
      }

      return gameData
      
    } catch (error) {
      console.error('加载游戏数据失败:', error)
      
      // 尝试从备份恢复
      const backupData = await this.restoreFromBackup()
      if (backupData) {
        return backupData
      }
      
      // 返回默认数据
      return this.getDefaultGameData()
    }
  }

  /**
   * 序列化数据
   */
  private serializeData(data: GameData): string {
    try {
      // 处理Date对象的序列化
      const serializedData = JSON.stringify(data, (key, value) => {
        if (value instanceof Date) {
          return { __type: 'Date', value: value.toISOString() }
        }
        return value
      })

      // 如果启用压缩，这里可以添加压缩逻辑
      if (this.config.compressionEnabled) {
        // 简单的压缩实现（实际项目中可以使用更好的压缩算法）
        return this.compressString(serializedData)
      }

      return serializedData
    } catch (error) {
      throw new StorageError(
        StorageErrorType.SERIALIZATION_ERROR,
        '数据序列化失败',
        error as Error
      )
    }
  }

  /**
   * 反序列化数据
   */
  private deserializeData(data: string): GameData {
    try {
      // 如果启用了压缩，先解压
      let jsonString = data
      if (this.config.compressionEnabled) {
        jsonString = this.decompressString(data)
      }

      // 反序列化并处理Date对象
      const gameData = JSON.parse(jsonString, (key, value) => {
        if (value && typeof value === 'object' && value.__type === 'Date') {
          return new Date(value.value)
        }
        return value
      })

      return gameData
    } catch (error) {
      throw new StorageError(
        StorageErrorType.CORRUPTION,
        '数据反序列化失败',
        error as Error
      )
    }
  }

  /**
   * 简单的字符串压缩（实际项目中应使用更好的算法）
   */
  private compressString(str: string): string {
    // 这里只是一个示例，实际应该使用专业的压缩库
    return btoa(str)
  }

  /**
   * 简单的字符串解压
   */
  private decompressString(str: string): string {
    try {
      return atob(str)
    } catch (error) {
      throw new Error('数据解压失败')
    }
  }

  /**
   * 创建数据备份
   */
  private async createBackup(): Promise<void> {
    try {
      const currentData = localStorage.getItem(this.config.storageKey)
      if (currentData) {
        const backupKey = `${this.config.storageKey}_backup_${Date.now()}`
        localStorage.setItem(backupKey, currentData)
      }
    } catch (error) {
      console.warn('创建备份失败:', error)
    }
  }

  /**
   * 从备份恢复数据
   */
  private async restoreFromBackup(): Promise<GameData | null> {
    try {
      const backupKeys: string[] = []
      
      // 安全地获取localStorage中的所有键
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i)
        if (key && key.startsWith(`${this.config.storageKey}_backup_`)) {
          backupKeys.push(key)
        }
      }

      // 按时间戳排序
      backupKeys.sort((a, b) => {
        const timeA = parseInt(a.split('_').pop() || '0')
        const timeB = parseInt(b.split('_').pop() || '0')
        return timeB - timeA // 最新的在前
      })

      for (const backupKey of backupKeys) {
        try {
          const backupData = localStorage.getItem(backupKey)
          if (backupData) {
            const gameData = this.deserializeData(backupData)
            console.log(`从备份 ${backupKey} 恢复数据`)
            return gameData
          }
        } catch (error) {
          console.warn(`备份 ${backupKey} 损坏，尝试下一个`)
          continue
        }
      }
    } catch (error) {
      console.error('从备份恢复失败:', error)
    }
    
    return null
  }

  /**
   * 清理旧备份
   */
  private async cleanupOldBackups(): Promise<void> {
    try {
      const backupKeys: string[] = []
      
      // 安全地获取localStorage中的所有键
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i)
        if (key && key.startsWith(`${this.config.storageKey}_backup_`)) {
          backupKeys.push(key)
        }
      }

      // 按时间戳排序
      backupKeys.sort((a, b) => {
        const timeA = parseInt(a.split('_').pop() || '0')
        const timeB = parseInt(b.split('_').pop() || '0')
        return timeB - timeA
      })

      // 保留最新的几个备份，删除其余的
      if (backupKeys.length > this.config.maxBackups) {
        const keysToDelete = backupKeys.slice(this.config.maxBackups)
        keysToDelete.forEach(key => {
          localStorage.removeItem(key)
        })
      }
    } catch (error) {
      console.warn('清理旧备份失败:', error)
    }
  }

  /**
   * 获取默认游戏数据
   */
  private getDefaultGameData(): GameData {
    return {
      settings: {
        soundEnabled: true,
        musicEnabled: true,
        masterVolume: 80,
        controlScheme: 'keyboard',
        difficulty: 'normal'
      },
      characterManager: null,
      gameStats: {
        totalScore: 0,
        totalDistance: 0,
        totalCoins: 0,
        gamesPlayed: 0,
        achievementsUnlocked: 0
      },
      scoreRecords: [],
      achievements: [],
      leaderboard: [],
      version: this.config.version,
      lastSaved: new Date()
    }
  }

  /**
   * 启动自动保存
   */
  private startAutoSave(): void {
    if (this.autoSaveTimer) {
      clearInterval(this.autoSaveTimer)
    }

    this.autoSaveTimer = window.setInterval(() => {
      // 这里可以触发自动保存事件
      console.log('自动保存触发')
    }, this.config.saveInterval)
  }

  /**
   * 停止自动保存
   */
  private stopAutoSave(): void {
    if (this.autoSaveTimer) {
      clearInterval(this.autoSaveTimer)
      this.autoSaveTimer = undefined
    }
  }

  /**
   * 清除所有数据
   */
  async clearAllData(): Promise<void> {
    try {
      // 删除主数据
      localStorage.removeItem(this.config.storageKey)
      
      // 删除所有备份
      const backupKeys: string[] = []
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i)
        if (key && key.startsWith(`${this.config.storageKey}_backup_`)) {
          backupKeys.push(key)
        }
      }
      
      backupKeys.forEach(key => {
        localStorage.removeItem(key)
      })
      
    } catch (error) {
      throw new StorageError(
        StorageErrorType.ACCESS_DENIED,
        '清除数据失败',
        error as Error
      )
    }
  }

  /**
   * 获取存储使用情况
   */
  getStorageUsage(): { used: number; total: number; percentage: number } {
    try {
      let used = 0
      for (let key in localStorage) {
        if (localStorage.hasOwnProperty(key)) {
          used += localStorage[key].length + key.length
        }
      }
      
      // localStorage通常限制为5-10MB，这里假设5MB
      const total = 5 * 1024 * 1024 // 5MB in bytes
      const percentage = (used / total) * 100
      
      return { used, total, percentage }
    } catch (error) {
      return { used: 0, total: 0, percentage: 0 }
    }
  }

  /**
   * 导出游戏数据
   */
  async exportGameData(): Promise<string> {
    const gameData = await this.loadGameData()
    return JSON.stringify(gameData, null, 2)
  }

  /**
   * 导入游戏数据
   */
  async importGameData(jsonData: string): Promise<void> {
    try {
      const gameData = JSON.parse(jsonData)
      await this.saveGameData(gameData)
    } catch (error) {
      throw new StorageError(
        StorageErrorType.SERIALIZATION_ERROR,
        '导入数据失败',
        error as Error
      )
    }
  }

  /**
   * 销毁存储管理器
   */
  destroy(): void {
    this.stopAutoSave()
    this.isInitialized = false
  }
}

/**
 * 全局存储管理器实例
 */
export const storageManager = new StorageManager()